package br.usp.icmc.biomac.client.view.lixo;

import java.util.ArrayList;
import java.util.List;

import br.usp.icmc.biomac.shared.ImageDicom;
import br.usp.icmc.biomac.shared.Line;
import br.usp.icmc.biomac.shared.Rectangle;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.CssColor;
import com.google.gwt.canvas.dom.client.FillStrokeStyle;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class DicomView extends Composite {

	@UiField
	HTMLPanel canvasArea;
	@UiField
	HTMLPanel drawArea;
	@UiField
	Label imageWC;
	@UiField
	Label imageWW;
	@UiField
	Label imageY;
	@UiField
	Label imageX;
	@UiField
	Label totalImage;
	@UiField
	Label levelImage;
	@UiField
	AbsolutePanel AbPanel;
	@UiField
	HTMLPanel slidePanel;
	@UiField Button btAnnotationMode;
	
	private final String elem = "canvas2";
	private final Canvas canvas;
	private Context2d context;
	private final Canvas slider;
	private Context2d slidercont;
	private static final int drawHeight = 512;
	private static final int drawWidth = 512;
	private static final int slideHeight = 35;
	private int mouseX, mouseY;
	private boolean clicado, imageLoad, mouseDownSlider = false;
	private int atualX, atualY, tool, imageIndex = 0;
	private final FillStrokeStyle strokeStyle = CssColor.make("#32CD32");// #333300
	private List<ImageDicom> images = new ArrayList<ImageDicom>();
	private ImageElement arrowSlideImage;
	private final Image logoImg = new Image("slider.png");
	private final FillStrokeStyle strokeStyleSlider = CssColor.make("#909090");// #333300
	private final FillStrokeStyle strokeStyleSliderArrow = CssColor
			.make("#FFFFFF");// #333300

	private static DicomViewUiBinder uiBinder = GWT
			.create(DicomViewUiBinder.class);

	interface DicomViewUiBinder extends UiBinder<Widget, DicomView> {
	}

	public DicomView() {
		initWidget(uiBinder.createAndBindUi(this));
		canvas = Canvas.createIfSupported();
		slider = Canvas.createIfSupported();
		// upImages.add
		if (canvas != null) {
			canvas.setWidth(drawWidth + "px");
			canvas.setHeight(drawHeight + "px");
			canvas.setCoordinateSpaceWidth(drawWidth);
			canvas.setCoordinateSpaceHeight(drawHeight);

			slider.setWidth(drawWidth + "px");
			slider.setHeight(slideHeight + "px");
			slider.setCoordinateSpaceWidth(drawWidth);
			slider.setCoordinateSpaceHeight(slideHeight);
			slidePanel.add(slider);
			drawArea.add(canvas);
			context = canvas.getContext2d();
			slidercont = slider.getContext2d();
			initHandlers();
			initHandlersSlider();
		} else {
			drawArea.add(new Label(
					"Your browser does not support the HTML5 Canvas. Please upgrade your browser to view this App."));
		}
		btAnnotationMode.setEnabled(false);
	}
	public void setData(List<ImageDicom> Images) {
		for (int i = 0; i < Images.size(); ++i) {
			addImage(Images.get(i).getUrl(), elem);
			Images.get(i).setId(Integer.toString(i));
			imageIndex = i;
		}
		this.images = Images;
		imageLoad = true;
		totalImage.setText(Integer.toString(Images.size()));
		levelImage.setText(Integer.toString(imageIndex + 1));
		drawArrow();
	}
	void initHandlers() {
		canvas.addMouseMoveHandler(new MouseMoveHandler() {
			@Override
			public void onMouseMove(MouseMoveEvent event) {
				mouseX = event.getRelativeX(canvas.getElement());
				mouseY = event.getRelativeY(canvas.getElement());
				imageX.setText(Integer.toString(mouseX));
				imageY.setText(Integer.toString(mouseY));
				switch (tool) {
				// change the coordinates numbers and change the brightness of
				// image
				case 0:
					if (imageLoad) {
						try {
							handleImageMouseMove(Integer.toString(mouseX),
									Integer.toString(mouseY));
							imageWC.setText(Integer.toString(wcImage()));
							imageWW.setText(Integer.toString(wwImage()));
						} catch (Exception e) {
							GWT.log("JSNI methodo handleImage() threw a exception: ",
									e);
							e.printStackTrace();
						}
					}
					break;
				// change the new line drawling
				case 1:
					if (clicado == true) {
						drawImage();
						// context.setStrokeStyle(strokeStyle);
						// context.clearRect(-1, -1, 512, 512);
						context.beginPath();
						context.lineTo(atualX, atualY);
						context.lineTo(mouseX, mouseY);
						context.closePath();
						context.stroke();
					}
					break;
				// change the new line drawling
				case 2: // change the new rectangle drawling
					if (clicado == true) {
						drawImage();
						// context.setStrokeStyle(strokeStyle);
						// context.clearRect(-1, -1, 512, 512);
						context.beginPath();
						context.rect(atualX, atualY, mouseX - atualX, mouseY
								- atualY);
						context.closePath();
						context.stroke();
					}
					break;
				}
			}
		});

		canvas.addMouseDownHandler(new MouseDownHandler() {// 1
			@Override
			public void onMouseDown(MouseDownEvent event) {
				atualX = mouseX;
				atualY = mouseY;
				switch (tool) {
				case 0:
					if (imageLoad) {
						handleImageMouseDown(Integer.toString(mouseX),
								Integer.toString(mouseY));
					}
					break;
				case 1:
					clicado = true;
					break;
				}
				clicado = true;
			}
		});
		canvas.addMouseUpHandler(new MouseUpHandler() {// 3
			@Override
			public void onMouseUp(MouseUpEvent event) {
				switch (tool) {
				case 0:
					if (imageLoad) {
						handleImageMouseUp();
					}
					break;
				case 1:
					if (clicado == true) {
						context.setStrokeStyle(strokeStyle);
						context.beginPath();
						context.lineTo(atualX, atualY);
						context.lineTo(mouseX, mouseY);
						context.closePath();
						context.stroke();
						clicado = false;
						//images.get(imageIndex).addLine("",atualX, atualY, mouseX, mouseY);
						drawImage();
					}
					break;
				case 2:
					if (clicado == true) {
						context.setStrokeStyle(strokeStyle);
						context.clearRect(-1, -1, 512, 512);
						context.beginPath();
						context.rect(atualX, atualY, mouseX - atualX, mouseY
								- atualY);
						context.closePath();
						context.stroke();
						clicado = false;
						//images.get(imageIndex).addRectangles("", atualX, atualY,mouseX - atualX, mouseY - atualY);
						drawImage();
					}
					break;
				}

			}
		});
		canvas.addMouseWheelHandler(new MouseWheelHandler() {
			@Override
			public void onMouseWheel(MouseWheelEvent event) {
				if (imageLoad) {
					if (event.getDeltaY() < 0) {
						upImages();
						if ((images.size() - 1) > imageIndex)
							++imageIndex;
					} else {
						downImages();
						if (0 < imageIndex)
							--imageIndex;
					}
					drawImage();
					drawArrow();
				}
			}
		});
	}

	void initHandlersSlider() {
		slider.addMouseMoveHandler(new MouseMoveHandler() {
			@Override
			public void onMouseMove(MouseMoveEvent event) {
				mouseX = event.getRelativeX(slider.getElement());
				mouseY = event.getRelativeY(slider.getElement());
				if (mouseDownSlider) {
					imageIndex = (mouseX / (drawWidth / images.size()));
					if (imageIndex > images.size())
						imageIndex = images.size();
					drawArrow();
				}

			}
		});

		slider.addMouseDownHandler(new MouseDownHandler() {// 1
			@Override
			public void onMouseDown(MouseDownEvent event) {
				imageIndex = (mouseX / (drawWidth / images.size()));
				if (imageIndex > images.size())
					imageIndex = images.size();
				drawArrow();
				mouseDownSlider = true;
				slider.setFocus(false);
			}
		});
		slider.addMouseUpHandler(new MouseUpHandler() {// 3
			@Override
			public void onMouseUp(MouseUpEvent event) {
				mouseDownSlider = false;
				slider.setFocus(false);
			}
		});
	}

	public void drawImage() {
		levelImage.setText(Integer.toString(imageIndex + 1));
		context.setStrokeStyle(strokeStyle);
		context.clearRect(-1, -1, 512, 512);
		//print ROI
		for (int a = 0; a < images.get(imageIndex).getRois().size(); ++a) {
			if(images.get(imageIndex).getRois().get(a) instanceof Line){
				context.beginPath();
				context.lineTo( ( (Line)images.get(imageIndex).getRois().get(a) ).getCood1().getX(), ( (Line)images.get(imageIndex).getRois().get(a) ).getCood1().getY());
				context.lineTo(( (Line)images.get(imageIndex).getRois().get(a) ).getCood2()
						.getX(), ( (Line)images.get(imageIndex).getRois().get(a) ).getCood2()
						.getY());
				context.closePath();
				context.stroke();
			}
			if(images.get(imageIndex).getRois().get(a) instanceof Rectangle){
				context.beginPath();
				context.rect(
						((Rectangle)images.get(imageIndex).getRois().get(a)).getCood1().getX(), 
						((Rectangle)images.get(imageIndex).getRois().get(a)).getCood1().getY(), 
						((Rectangle)images.get(imageIndex).getRois().get(a)).getCood2().getX(), 
						((Rectangle)images.get(imageIndex).getRois().get(a)).getCood2().getY() );
				context.closePath();
				context.stroke();
			}
			
		}
		table_ROIS();
	}

	public void drawArrow() {
		if (!imageLoad)
			return;
		arrowSlideImage = (ImageElement) logoImg.getElement().cast();
		double elemento = imageIndex * ((drawWidth / images.size()));
		elemento += (drawWidth / images.size() / 2);
		// clean context 2d
		slidercont.setStrokeStyle(strokeStyleSlider);
		slidercont.clearRect(-1, -1, 512, 50);
		// draw a grade elements
		for (int i = 0; i < images.size(); ++i) {
			slidercont.beginPath();
			int x = ((drawWidth / images.size()) * (i))
					+ (drawWidth / images.size() / 2);
			slidercont.lineTo(x, 0);
			slidercont.lineTo(x, 15);
			slidercont.closePath();
			slidercont.stroke();
		}
		slidercont.setStrokeStyle(strokeStyleSliderArrow);
		slidercont.beginPath();
		slidercont.lineTo((int) elemento, 0);
		slidercont.lineTo((int) elemento, 15);
		slidercont.closePath();
		slidercont.stroke();
		slidercont.drawImage(arrowSlideImage, (int) elemento - 5, 15);
		changeLevelImage(imageIndex);
		drawImage();
		slider.setFocus(false);
	}

	public void table_ROIS(){
		
	}
	public native String loadImages()/*-{
		$wnd.startImage();
	}-*/;

	public native String upImages()/*-{
		$wnd.moveCamada(1);
	}-*/;

	public native String downImages()/*-{
		$wnd.moveCamada(-1);
	}-*/;

	public native String b_add()/*-{
		$wnd.applyBrilho(-1);
	}-*/;

	public native String b_rmv()/*-{
		$wnd.applyBrilho(1);
	}-*/;

	public native String c_add()/*-{
		$wnd.applycontraste(1);
	}-*/;

	public native String c_rmv()/*-{
		$wnd.applycontraste(-1);
	}-*/;

	public native String resetImages()/*-{
		$wnd.reset(-1);
	}-*/;

	public native String handleImageMouseMove(String x, String y)/*-{
		$wnd.mousemoveHandler2(x, y);
	}-*/;

	public native String handleImageMouseUp()/*-{
		$wnd.mouseupHandler2();
	}-*/;

	public native String handleImageMouseDown(String x, String y)/*-{
		$wnd.mouseDownHandler2(x, y);
	}-*/;

	public native String addImage(String url, String elem)/*-{
		$wnd.addImage(url, elem);
	}-*/;

	public native int wcImage()/*-{
		return $wnd.WebPad_wc;
	}-*/;

	public native int wwImage()/*-{
		return $wnd.WebPad_ww;
	}-*/;

	public native String changeLevelImage(int id)/*-{
		$wnd.changeLevelImage(id);
	}-*/;

}
